package com.example.origin.demo.demo;

import lombok.SneakyThrows;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;

// 数据库连接池涉及的关键点包括连接的创建、复用、回收
public class SimpleDatabaseConnectionPool {
    // 配置属性
    private final int initialSize;
    private final int maxSize;
    private final String url;
    private final String username;
    private final String password;
    private final Queue<Connection> connectionPool;

    private AtomicInteger useCount = new AtomicInteger(0);

    public SimpleDatabaseConnectionPool(int initialSize, int maxSize, String url, String username, String password) {
        this.initialSize = initialSize;
        this.maxSize = maxSize;
        this.url = url;
        this.username = username;
        this.password = password;
        connectionPool = new LinkedList<>();
        initializePool();
    }

    /**
     * 创建：初始化连接（起始连接数），放入连接池中（queue）
     */
    private void initializePool() {
        try {
            Class.forName("com.mysql.jdbc.Driver"); // 假设使用MySQL数据库
            for (int i = 0; i < initialSize; i++) {
                Connection conn = DriverManager.getConnection(url, username, password);
                connectionPool.offer(conn);
            }
        } catch (ClassNotFoundException | SQLException e) {
            throw new RuntimeException("初始化连接池失败", e);
        }
    }

    /**
     * 复用：加锁，如果连接池中有连接，即返回（poll）
     * 无连接，如果已使用连接数<=最大连接数，是则创建，放入连接池中，否则等待（wait）
     * @return
     * @throws InterruptedException
     * @throws SQLException
     */
    public Connection getConnection() throws InterruptedException, SQLException {
        synchronized (connectionPool) {
            while (connectionPool.isEmpty()) {
                if (useCount.get() <= maxSize) {
                    Connection conn = createNewConnection();
                    connectionPool.offer(conn);
                } else {
                    connectionPool.wait();
                }
            }
            useCount.incrementAndGet();
            return connectionPool.poll();
        }
    }

    private Connection createNewConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }

    /**
     * 回收：加锁，如果线程池中连接数<=初始化连接数，当前连接回收池中，否则，关闭连接
     * 最后唤醒（等待创建连接的线程）
     * @param conn
     */
    @SneakyThrows
    public void releaseConnection(Connection conn) {
        if (conn != null && !conn.isClosed()) {
            synchronized (connectionPool) {
                if (connectionPool.size() <= initialSize) {
                    try {
                        // 清理和重置连接状态
                        conn.clearWarnings();
                        conn.setAutoCommit(true);
                        connectionPool.offer(conn);
                    } catch (SQLException e) {
                        // 关闭无法复用的连接
                        closeConnection(conn);
                    }
                } else {
                    closeConnection(conn);
                }
                connectionPool.notifyAll();
            }
        }
    }

    private void closeConnection(Connection conn) {
        try {
            if (!conn.isClosed()) {
                conn.close();
                useCount.decrementAndGet();
            }
        } catch (SQLException ignored) {
            // 忽略关闭异常
        }
    }

    // 其他必要的生命周期管理方法，如shutdown等
    // 清理连接池，在程序退出前关闭所有连接
    public void shutdown() {
        Connection connection;
        while ((connection = connectionPool.poll()) != null) {
            try {
                if (!connection.isClosed()) {
                    connection.close();
                }
            } catch (SQLException e) {
                // 记录日志，但不应阻止其他连接的关闭
                e.printStackTrace();
            }
        }
    }
}